use std::future::Future;
use std::ops::Deref;
use axum::{Extension, Json, TypedHeader};
use axum::async_trait;
use axum::extract::{FromRequest, RequestParts};
use axum::headers::Cookie;
use axum::http::StatusCode;
use rbatis::Error;
use tracing::{debug, error, info};
use cores::responses::CusResponse;
use cores::sessions::Session;
use cores::{AppError, Result};
use crate::dao::User;
use crate::service::fetch_user_by_id;

pub struct UserAuthMiddleware(pub User);

#[async_trait]
impl<B> FromRequest<B> for UserAuthMiddleware
    where
        B: Send,
{
    // type Rejection = (StatusCode, Json<CusResponse<String>>);
    type Rejection = AppError;
    async fn from_request(req: &mut RequestParts<B>) -> Result<Self> {
        let Extension(session) = Extension::<Session>::from_request(req)
            .await
            .expect("`Session` extension missing");
        let _c = TypedHeader::<Cookie>::from_request(req).await?;
        let cookie = _c.deref().clone();
        match session.get_session_data(cookie).await {
            Ok(session_data) => {
                let user_id = (*session_data.data.get("user_id").unwrap()).clone();
                Ok(UserAuthMiddleware(fetch_user_by_id(user_id).await?))
            }
            Err(_) => {
                Err(AppError::from_str("请登录", 401))
            }
        }
    }
}